﻿#pragma once

#include <cstdint>
#include <emmintrin.h>

template <typename T>
class atomic_integerT
{
public:
	atomic_integerT() : m_value(0) {}
	atomic_integerT(T value)
	{
		m_value = value;
	}
	T get()
	{
		return __sync_val_compare_and_swap(&m_value, 0, 0);
	}

	void set(T new_value)
	{
		getAndSet(new_value);
	}

	T getAndSet(T new_value)
	{
		return __sync_lock_test_and_set(&m_value, new_value);
	}

	T add(T x)
	{
		return addAndGet(x);
	}
	T fetch_add(T x)
	{
		return __sync_fetch_and_add(&m_value, x);
	}
	void increment()
	{
		incrementAndGet();
	}

	void decrement()
	{
		decrementAndGet();
	}

	T incrementAndGet()
	{
		return addAndGet(1);
	}

	T decrementAndGet()
	{
		return addAndGet(-1);
	}

private:
	T addAndGet(T x)
	{
		return __sync_add_and_fetch(&m_value, x);
	}

	T getAndAdd(T x)
	{
		return __sync_fetch_and_add(&m_value, x);
	}

private:
	volatile T m_value;
};

typedef atomic_integerT<int32_t> atomic_int32;
typedef atomic_integerT<int64_t> atomic_int64;

/// ultra low latency cpu pause
static inline void ull_pause()
{
	_mm_pause();
};

